/**
 * \file  antiviral_selector.h
 * \brief Definition of Antiviral Selector class.
 *
 * LAV: Lib Anti Virals
 * <http://aso.googlecode.com/>
 * Copyright (C) 2010, 2012 Velez Ezequiel, Peralta Andres, Bettiol Favio, Diaz Diego, 
 *                     2013 Lenarduzzi Federico, Boretto Martin, Alberione Fernando, Ocampo Emanuel.
 *
 * This file is part of the LAV project.
 *
 * Contents:       Definition of Antiviral Selector class. 
 *
 * System:         LAV
 * Language:       C++
 *
 * \authors Velez Ezequiel, Peralta Andres, Boretto Martin, Lenarduzzi Federico, Ocampo Emanuel, Alberione Fernando.
 *
 * LAV is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LAV is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ASO.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#ifndef ANTIVIRAL_SELECTOR_H
#define ANTIVIRAL_SELECTOR_H

#include <iostream>
#include <cmath>
#include "lav/data_base.h"
#include "lav/optimized_container.h"


namespace lav
{

const double PMUT = 1.0 / 10000;
const size_t FACTORIAL_MAX_VALUE = 3;


/**
 * \struct AvProbPair represent a pair (antiviral, probability). 
 */
struct AvProbPair
{
	ResisBasedAntiviral _av;
    double _prob;

    /**
	 * Constructor
     */
    AvProbPair(const ResisBasedAntiviral& av, double prob)
        : _av(av), _prob(prob) {}

    /**
     * Comparison operation.
     */    
    bool operator < (const AvProbPair& other) const
    {
        return (_prob < other._prob);
    }
};


/**
 * \struct AvProbPairUnique 
 * \brief Contains an operation to compare between two pair's names.
 */
struct AvProbPairUnique
{
    bool operator()(const AvProbPair& p1, const AvProbPair& p2) const
    {
        AntiviralsNames av_1;
        AntiviralsNames av_2;
        p1._av.get_attrib("name", av_1);
        p2._av.get_attrib("name", av_2);
        return av_1 > av_2;
    }
};


/**
 * \struct AvProbPairRanking
 * \brief Contains an operation to compare between two pair's probablities.
 */
struct AvProbPairRanking
{
    bool operator()(const AvProbPair& p1, const AvProbPair& p2) const
    {
        return p1._prob < p2._prob;
    }
};


typedef mili::UniqueRanker<AvProbPair, AvProbPairRanking, AvProbPairUnique> RankAvProb;


/**
 * \class AntiviralSelector
 * \brief This class contains the functions to build the ranking of antivirals.
 */
class AntiviralSelector
{
public:
    inline void select_antivirals(const AntiviralSet& antiviral_set, const biopp::PseudoNucSequence& sequence, AntiviralSet& applicable_avs);
    inline void rank_antivirals(const AntiviralSet& antiviral_set, const biopp::PseudoNucSequence& sequence, RankAvProb& rank);

private:
	template <class T>
    static T factorial(size_t n);

    inline void process_resistances(const ResisBasedAntiviral::ResistancePositionContainer::const_iterator& it_res, 
    								const biopp::PseudoNucSequence& sequence, 
    								double p);
};

}


#define ANTIVIRAL_SELECTOR_INLINE_H
#include "antiviral_selector_inline.h"
#undef ANTIVIRAL_SELECTOR_INLINE_H

#endif


